// 版权所有2009 Go作者。保留所有权利。
// 此源代码的使用受BSD样式
// 许可证的约束，该许可证可以在许可证文件中找到。

// 软件包实现了在加密
// 代码中经常有用的函数，但需要仔细考虑才能正确使用。
package subtle

// 如果x和y这两个片的内容相等，则ConstantTimeCompare返回1，否则返回0。所用时间是切片长度的函数，
// 与内容无关。
func ConstantTimeCompare(x, y []byte) int {
	if len(x) != len(y) {
		return 0
	}

	var v byte

	for i := 0; i < len(x); i++ {
		v |= x[i] ^ y[i]
	}

	return ConstantTimeByteEq(v, 0)
}

// 如果v==1，ConstantTimeSelect返回x，如果v==0，则返回y。
// 如果v取任何其他值，则其行为未定义。
func ConstantTimeSelect(v, x, y int) int { return ^(v-1)&x | (v-1)&y }

// constanttimebyteq如果x==y则返回1，否则返回0。
func ConstantTimeByteEq(x, y uint8) int {
	return int((uint32(x^y) - 1) >> 31)
}

// ConstantTimeEq如果x==y则返回1，否则返回0。
func ConstantTimeEq(x, y int32) int {
	return int((uint64(uint32(x^y)) - 1) >> 63)
}

// ConstantTimeCopy将y的内容复制到x（长度相等的切片）
// 如果v==1。如果v==0，x保持不变。如果v 
// 接受任何其他值，则其行为未定义。
func ConstantTimeCopy(v int, x, y []byte) {
	if len(x) != len(y) {
		panic("subtle: slices have different lengths")
	}

	xmask := byte(v - 1)
	ymask := byte(^(v - 1))
	for i := 0; i < len(x); i++ {
		x[i] = x[i]&xmask | y[i]&ymask
	}
}

// ConstantTimeLessOrEq如果x<=y则返回1，否则返回0。
// 如果x或y为负或>2**31-1，则其行为未定义。
func ConstantTimeLessOrEq(x, y int) int {
	x32 := int32(x)
	y32 := int32(y)
	return int(((x32 - y32 - 1) >> 31) & 1)
}
